/**
 * 
 */
package cz.cuni.mff.abacs.burglar.logics.objects;

import cz.cuni.mff.abacs.burglar.logics.DataMap;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Agent;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Position;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


/**
 * Representation of a room. 
 * 
 * Rooms may contain positions and agents.
 * They are connected through rooms.
 * 
 * <ul>
 *   <li>agent can be discovered in</li>
 *   <li>it can be light/dark</li>
 * </ul>
 * 
 * @author abacs
 */
public class Room extends BaseObject {
	
	
	/** X Coordinate of the "bottom left" corner of the room. */
	private int _x = 0;
	/** Y Coordinate of the "bottom left" corner of the room. */
	private int _y = 0;
	/** Width of the room on the game map. */
	private int _width = 0;
	/** Height of the room on the game map. */
	private int _height = 0;
	/** List of positions inside the room. */
	private List<Integer> _positionIds = new LinkedList<Integer>();
	
	
	// -------------------------------------------------------------------------
	
	
	/** Indicator whether there are lights lit in the room.
	 * 
	 * not used.
	 */
	private boolean _isLit = true;
	
	
	// -------------------------------------------------------------------------
	// constructors:
	
	
	/**
	 * Default lighting state is true.
	 * 
	 * @param id
	 * @param x
	 * @param y
	 * @param height
	 * @param width
	 * @param referenceMap
	 */
	public Room(
			int id,
			int x,
			int y,
			int height,
			int width,
			DataMap referenceMap
	) {
		super(id, BaseObject.Type.ROOM, referenceMap);
		this._x = x;
		this._y = y;
		this._width = width;
		this._height = height;
	}
	
	
	/**
	 * Special copy constructor with replaced parent object.
	 * 
	 * @param other object to copy.
	 * @param referenceMap parent object to use.
	 */
	protected Room(Room other, DataMap referenceMap) {
		super(other.getId(), other.getType(), referenceMap);
		this._x = other._x;
		this._y = other._y;
		this._width = other._width;
		this._height = other._height;
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Adds a single position to the room.
	 * 
	 * It does not check the position's coordinates.
	 */
	public void addPosition(Position position) {
		this._positionIds.add(position.getId());
	}
	
	
	/**
	 * Sets the lighting state in the room.
	 * 
	 * @param isLit true if lit
	 */
	public void setIsLit(boolean isLit) {
		this._isLit = isLit;
	}
	
	
	// -------------------------------------------------------------------------
	// getters:
	
	
	/** 
	 * Returns all the {@link Position positions} found in the room.
	 * 
	 * @return positions in the room.
	 */
	public List<Position> getPositions() {
		List<Position> ret = new LinkedList<Position>();
		for(Integer id : this._positionIds){
			Position pos = this._referenceMap.getPosition(id);
			if(pos != null){
				ret.add(pos);
			}
		}
		return ret;
	}
	
	
	/**
	 * Returns all the operable (active) 
	 * {@link Position positions} found in the room.
	 * 
	 * @return 
	 */
	public List<Position> getOperablePositions() {
		List<Position> ret = new LinkedList<Position>();
		for(Position pos : this.getPositions())
			
			if(pos.isOperable())
				ret.add(pos);
			
		return ret;
	}
	
	
	/**
	 * Returns all the operable (active) 
	 * {@link Position positions} found in the room.
	 * 
	 * @return 
	 */
	public List<Agent> getAgents() {
		List<Agent> ret = new ArrayList<Agent>();
		for(Agent agent : this._referenceMap.getAgents())
			
			if(agent.isInRoom(this))
				ret.add(agent);
			
		return ret;
	}
	
	
	/**
	 * Are the lights lit in the room?
	 * 
	 * @return true if is lit.
	 */
	public boolean getIsLit() {
		return this._isLit;
	}
	
	
	/**
	 * Get the left top corner x coordinate.
	 * 
	 * @return horizontal coordinate
	 */
	public int getX() {
		return this._x;
	}
	
	
	/** 
	 * Get the left top corner y coordinate.
	 * 
	 * @return vertical coordinate
	 */
	public int getY() {
		return this._y;
	}
	
	
	/** 
	 * Get the horizontal dimension of the room.
	 * 
	 * @return width in positions
	 */
	public int getWidth() {
		return this._width;
	}
	
	
	/** 
	 * Get the vertical dimension of the room.
	 * 
	 * @return height in positions
	 */
	public int getHeight() {
		return this._height;
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Not used.
	 */
	public boolean checkIntegrity() {
		
		// TODO
		
		return true;
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Copies the details of the other room that might change through the gameplay.
	 * 
	 * @param original
	 */
	public void copyChangeables(Room original) {
		this._isLit = original._isLit;
		
		for(Integer posId : original._positionIds)
			this._positionIds.add(posId);
	}
	
	
	/**
	 * Creates a copy of itself with a difference reference map.
	 * 
	 * @param referenceMap
	 * @return a copy of itself
	 */
	public Room copy(DataMap referenceMap) {
		return new Room(this, referenceMap);
	}
	
	
}
